import uuid
from typing import Any

import pytest

from recruit.adapter.database.models import User
from recruit.application.commands.update_user import UserUpdateDTO
from recruit.domain.exceptions.user import (
    UserExistsError,
    UserNotFoundException,
)
from recruit.domain.models.user import UserCreate, UserResult
from recruit.domain.services.user import UserService


def test_check_user_exists() -> None:
    assert UserService().check_user_exists(False) is None
    with pytest.raises(UserExistsError):
        UserService().check_user_exists(True)


def test_check_user() -> None:
    assert UserService().check_user(True) is None
    with pytest.raises(UserNotFoundException):
        UserService().check_user(False)


@pytest.mark.parametrize(
    'data', [
        {
            'user_id': 1,
            'username': '@username'
        }
    ]
)
def test_create_user(data: dict[str, Any]) -> None:
    user = UserService().create_user(UserCreate(**data))
    assert isinstance(user, dict)
    assert sorted((tuple(user))) == sorted(tuple(data))
    assert isinstance(user['user_id'], str)
    assert user['user_id'] == str(data['user_id'])
    assert user['username'] == data['username']


@pytest.mark.parametrize(
    'data', [
        {
            'id': uuid.uuid4(),
            'user_id': '1',
            'username': '@username'
        }
    ]
)
def test_get_user(data: dict[str, Any]) -> None:
    user = UserService().get_user(User(**data))
    assert isinstance(user, UserResult)
    assert user.id == data['id']
    assert user.user_id == int(data['user_id'])
    assert user.username == data['username']
    with pytest.raises(UserNotFoundException):
        UserService().get_user(None)


@pytest.mark.parametrize(
    'data', [{
        'id': uuid.uuid4(),
        'username': '@username'
    }]
)
def test_update_user(data: dict[str, Any]) -> None:
    user = UserService().update_user(UserUpdateDTO(**data))
    assert isinstance(user, dict)
    assert user.get('username')
    assert user['username'] == data['username']
